package com.liwei.filesearch.concurrent;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.Callable;

import com.liwei.filesearch.SingleSearchResult;

/**
 * This task counts the files in a directory and its subdirectories that contain
 * a given keyword.
 */
public class MatchFiles implements Callable<SingleSearchResult> {

	private File directory;
	private String keyword;
	private Set<String> fileSet = new HashSet<String>();

	public static Set<String> extSet;
	static {
		extSet = new HashSet<String>();
		extSet.add(".java");
		extSet.add(".xml");
		extSet.add(".vm");
	}

	/**
	 * Constructs a MatchCounter.
	 * 
	 * @param directory
	 *            the directory in which to start the search
	 * @param keyword
	 *            the keyword to look for
	 */
	public MatchFiles(File directory, String keyword) {
		this.directory = directory;
		this.keyword = keyword;
	}

	public SingleSearchResult call() {
		digui(directory);

		FileUtil.writeFileByLines(keyword, fileSet);

		SingleSearchResult ssr = new SingleSearchResult();
		ssr.setKeyword(keyword);
		ssr.setSet(fileSet);

		return ssr;
	}

	public void digui(File file2) {
		File[] files = file2.listFiles();

		for (File file : files) {
			if (file.isDirectory()) {
				digui(file);
			} else {
				boolean extmatch = false;
				for (String ext : extSet) {
					if (file.getName().endsWith(ext)) {
						if (!file.getAbsolutePath().contains(".test")) {
							extmatch = true;
							break;
						}
						// else {
						// System.out.println(file.getAbsolutePath());
						// }
					}
				}
				if (extmatch) {
					String name = search(file);
					if (name != null) {
						fileSet.add(name);
					}
				}
			}
		}
	}

	/**
	 * Searches a file for a given keyword.
	 * 
	 * @param file
	 *            the file to search
	 * @return true if the keyword is contained in the file
	 */
	public String search(File file) {
		try {
			Scanner in = new Scanner(new FileInputStream(file));
			boolean found = false;
			while (!found && in.hasNextLine()) {
				String line = in.nextLine();
				if (line.contains(keyword))
					found = true;
			}
			in.close();
			if (found) {
				return file.getAbsolutePath();
			} else {
				return null;
			}

		} catch (IOException e) {
			return null;
		}
	}
}